package com.android.monee.binding.observable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.android.monee.binding.Field;
import com.android.monee.binding.observer.Observer;



public class ObservableImpl<S> implements Observable<S>{

	private Map<Class<?>, List<Observer>> observerMap;
	private S observedData;
	
	/**
	 * Si on utilise ObservableImpl2 en délégation pour implémenter Observable2.
	 * @param source L'object rendu observable par délégation.
	 */
	public ObservableImpl(S observedData){
		this.observedData = observedData;
		this.observerMap = new HashMap<Class<?>, List<Observer>>();
	}
	
	/**
	 * Si on hérite de ObservableImpl2 pour implémenter Observable2.
	 */
	public ObservableImpl(){
		this.observedData = (S) this;
		this.observerMap = new HashMap<Class<?>, List<Observer>>();
	}
	
	public <T, V> void addObserver(Observer<S, T, V> observer) {
		Class<? extends Field> fieldClass = observer.getSourceField().getClass();
		if(!observerMap.containsKey(fieldClass)){
			List<Observer> list = new ArrayList<Observer>();
			observerMap.put(fieldClass, list);
		}
		List<Observer> observerList = observerMap.get(fieldClass);
		observerList.add(observer);
		
		//observer.updateTarget(this.observedData);
	}

	@Override
	public <T, V> void deleteObserver(Observer<S, T, V> observer) {
		for(List<Observer> list : observerMap.values()){
			int index = 0;
			for(Observer<S, T, V> obs : list){
				if(observer.equals(obs)){
					list.remove(index);
					return;
				}
				index++;
			}
		}
	}

	@Override
	public <T, V> void notify(Class<? extends Field> fieldClass) {
		List<Observer> observerList = observerMap.get(fieldClass);
		if (observerList != null) {
			for (Observer<S, T, V> obs : observerList) {
				obs.updateTarget(this.observedData);
			}
		}		
	}

	@Override
	public S getObservedData() {
		return this.observedData;
	}
}
